/* eslint-disable @typescript-eslint/no-unused-vars */
import type { Meta, StoryObj } from "@storybook/react"
import { Button, Col, Divider, Flex, Form, Input, Row, Select } from "antd"
import { useState } from "react"

import { QueryForm, SFlex, Slot } from "../common"
import { Toast } from "../messages"
import * as FormItems from "."

const skipList = ["id", "pageNum", "pageSize"]
const timeList = [
	"startDate",
	"endDate",
	"createdAt",
	"updatedAt",
	"createAtBegin",
	"createAtEnd",
	"updatedAtBegin",
	"updatedAtEnd",
	"startCreatedAt",
	"endCreatedAt",
	"startUpdatedAt",
	"endCreatedAt",
	"loginAt",
	"startLoginAt",
	"endLoginAt",
	"loginAtBegin",
	"loginAtEnd",
	"createdStartAt",
	"createdEndAt",
	"updatedStartAt",
	"updatedEndAt"
]

type FieldType = {
	input: string
}

type FormItemKeys = keyof typeof FormItems

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
	title: "FormItems",
	component: QueryForm,
	parameters: {
		// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
		layout: "fullscreen"
	},
	tags: ["autodocs"]
	// More on argTypes: https://storybook.js.org/docs/api/argtypes
	// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
} satisfies Meta<typeof QueryForm>

export default meta
type Story = StoryObj<typeof meta>

export const FormItemsSearch: Story = {
	render: args => {
		const options = Object.entries(FormItems)
			.filter(([key]) => {
				const firstLetter = key.charAt(0)
				return firstLetter === firstLetter.toUpperCase()
			})
			.map(([key, value]) => {
				let fieldName = null
				const nameRegex = /name:\s*"([^"]*)"/
				const match = value.toString().match(nameRegex)
				if (match) {
					fieldName = match[1]
				}
				return {
					label: key,
					value: key,
					fieldName,
					combine: `${key}${fieldName}`
				}
			})
			.filter(option => !!option.fieldName)

		const filterOption = (input: string, option?: { label: string; value: string; combine: string }) =>
			(option?.combine ?? "").toLowerCase().includes(input.replaceAll(" ", "").toLowerCase())

		const [items, setItems] = useState([])

		return (
			<SFlex vertical justify="flex-end" style={{ padding: "20px" }}>
				<h2>Form Items Search</h2>
				<Select
					allowClear
					mode="multiple"
					style={{ width: "100%" }}
					options={options}
					onChange={setItems}
					maxTagCount="responsive"
					placeholder="Search..."
					placement="topLeft"
					maxCount={10}
					filterOption={filterOption}
					optionRender={({ data }: any) => {
						return (
							<Flex gap="10px">
								<span>Component name: {data.value}</span>
								<span>/</span>
								<span>Field name: {data.fieldName}</span>
							</Flex>
						)
					}}
				/>
				<QueryForm>
					<Slot slotname="formItems">
						<br />
						{items.map((name, index) => {
							const InputComponent = FormItems[name] as any
							// eslint-disable-next-line react/jsx-key
							return <InputComponent key={index} />
						})}
					</Slot>
				</QueryForm>
			</SFlex>
		)
	}
}

export const AutoFormItemsGenerator: Story = {
	render: args => {
		const options = Object.entries(FormItems)
			.filter(([key]) => {
				const firstLetter = key.charAt(0)
				return firstLetter === firstLetter.toUpperCase()
			})
			.map(([key, value]) => {
				let fieldName = null
				const nameRegex = /name:\s*"([^"]*)"/
				const match = value.toString().match(nameRegex)
				if (match) {
					fieldName = match[1]
				}
				return {
					label: key,
					value: key,
					fieldName,
					combine: `${key}${fieldName}`
				}
			})
			.filter(option => !!option.fieldName)

		const [insertions, setInsertions] = useState<string[]>([])
		const [missing, setMissing] = useState<string[]>([])
		const [hasTimePicker, setHasTimePicker] = useState<boolean>(false)

		const [submitForm] = Form.useForm<FieldType>()
		const submit = ({ input }: FieldType) => {
			setHasTimePicker(false)
			try {
				JSON.parse(input)
			} catch (e) {
				Toast.error("Please input in JSON format")
				return
			}
			const keys = Object.keys(JSON.parse(input))
				.map(key => {
					if (skipList.includes(key)) return ""
					if (timeList.includes(key)) {
						setHasTimePicker(true)
						return key
					}
					return key
				})
				.filter(Boolean)

			const insertions = options.map((item): any => item.fieldName).filter(item => keys.includes(item))
			setInsertions([])
			setTimeout(() => {
				setInsertions(insertions)
			}, 0)

			const differences = keys.filter(item => !insertions.includes(item))
			setMissing(differences)
		}

		const input = submitForm.getFieldValue("input")

		return (
			<>
				<SFlex vertical justify="flex-end" style={{ padding: "20px" }}>
					<h2>Auto Form Items Generator</h2>
					<Form
						initialValues={{
							input: JSON.stringify(
								{
									terminalInfo: "1.1.1.3",
									ipAttribution: "澳大利亚",
									typeId: 1,
									pageNum: 1,
									pageSize: 100,
									startCreatedAt: "2024-05-15 00:00:00",
									endCreatedAt: "2024-05-15 23:59:59",
									createdBy: "Quan",
									merchantId: "789469140550905867"
								},
								null,
								2
							)
						}}
						form={submitForm}
						labelCol={{ span: 4 }}
						wrapperCol={{ span: 16 }}
						style={{ maxWidth: "100%" }}
						onFinish={submit}
					>
						<Form.Item
							colon
							label="Request payload"
							name="input"
							rules={[{ required: true, message: "Please input object record!" }]}
						>
							<Input.TextArea rows={10} />
						</Form.Item>
						<Form.Item wrapperCol={{ offset: 8, span: 16 }}>
							<Button type="primary" htmlType="submit">
								Generate form items
							</Button>
						</Form.Item>
					</Form>
					<Divider />
				</SFlex>
				<Row wrap>
					<Col span={12}>
						{insertions.length > 0 && (
							<pre>
								Existed input items:
								{JSON.stringify(
									[
										...options
											.filter((item: any) => insertions.includes(item.fieldName))
											.map(item => {
												let name = item.fieldName
												console.log("name:", name, name?.includes("min"))
												if (name?.includes("min")) {
													name = `${name}|${name.replace("min", "max")}`
												}
												return `${name} - ${item.value}`
											}),
										hasTimePicker
											? `${Object.keys(JSON.parse(input))
													.filter(key => timeList.includes(key))
													.join("|")} - TimeRangePicker`
											: ""
									].filter(Boolean),
									null,
									2
								)}
							</pre>
						)}
					</Col>
					<Col span={12}>
						{missing.length > 0 && (
							<pre>
								New field:
								{JSON.stringify(
									missing.filter(item => !timeList.includes(item) && !item.includes("max")),
									null,
									2
								)}
							</pre>
						)}
					</Col>
					<Col span={24}>
						{insertions.length > 0 && (
							<SFlex vertical>
								<Divider />
								<h4>Sample Form Items</h4>
								<QueryForm>
									<Slot slotname="formItems">
										{(
											[
												...options.filter((item: any) => insertions.includes(item.fieldName)).map(item => item.value),
												hasTimePicker ? "TimeRangePicker" : ""
											].filter(Boolean) as FormItemKeys[]
										).map((name, index) => {
											const InputComponent = FormItems[name] as React.FC
											// eslint-disable-next-line react/jsx-key
											return <InputComponent key={index} />
										})}
									</Slot>
								</QueryForm>
							</SFlex>
						)}
					</Col>
				</Row>
			</>
		)
	}
}
